/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkSipUdpListener.h"
#include "MkSipMessage.h"
#include "MkSip/MkSipServer.h"
#include "MkUtil/MkLog.h"
#include "MkUtil/MkUtil.h"

CMkSipUdpListener::CMkSipUdpListener(CMkEvent* pEvent, CMkTimer* pTimer, CMkSipServer* pParent)
    : CMkSipListener(pParent)
    , CMkSocket(UdpSession, pEvent, pTimer)
    , m_MaxRecvLen(LenHalfM)
    , m_pRecvBuffer((Uint8*)malloc(LenHalfM))
{
    memset(m_pRecvBuffer, 0, LenHalfM);
}

Uint32 CMkSipUdpListener::Start(const MkString& ListenHost, Uint16 ListenPort, const MkString& PublicHost, Uint16 PublicPort)
{
    Uint32 ErrorCode = Create();
    MkCheckErrorLog(ErrorCode, "sip udp server create socket failed\n");
    ErrorCode = Bind(ListenPort, ListenHost);
    MkCheckErrorLog(ErrorCode, "sip udp server bind(%s:%d) failed\n", ListenHost.c_str(), ListenPort);
    return CMkSipListener::Start(ListenHost, ListenPort, PublicHost, PublicPort);
}

Uint32 CMkSipUdpListener::SendSipMessage(const CMkSipMessage& SipMessage, const SipMsgCompleteCallback& Cb/* = nullptr*/, BOOL bResend/* = FALSE*/)
{
    MkString StrSipMsg;
    if (!bResend
        && SipMessage.IsRequest()
        && MkSipMethodAck != SipMessage.GetMethod()) {
        CMkSipMessage SendMsg = SipMessage;
        CMkSipVia Via;
        Via.SetProtocol("UDP");
        Via.UpdateParam("rport", "");
        Via.SetBranch("z9hG4bK" + std::to_string(CMkUtil::GetRandomNumber()));
        Via.SetHost(GetListenHost());
        Via.SetPort(GetListenPort());
        SendMsg.AddVia(Via);
        SendMsg.ToString(StrSipMsg);
        if (Cb) {
            Cb(SendMsg);
        }
    } else {
        SipMessage.ToString(StrSipMsg);
        if (Cb) {
            Cb(SipMessage);
        }
    }
    if (CMkSipUtil::GetInstance().DebugMessageContent()) {
        MkDebugLog("send sip message:\n%s\n", StrSipMsg.c_str());
    }
    MkString SendHost = SipMessage.GetContactHost().empty() ? SipMessage.GetRemoteHost() : SipMessage.GetContactHost();
    Uint16 SendPort = SipMessage.GetContactHost().empty() ? SipMessage.GetRemotePort() : SipMessage.GetContactPort();
    return SendTo(SendHost, SendPort, (const Uint8*)StrSipMsg.c_str(), StrSipMsg.size());
}

Uint32 CMkSipUdpListener::OnRecvFrom()
{
    Uint32 nLen = m_MaxRecvLen;
    MkString RemoteIp;
    Uint16 RemotePort;
    Uint32 ErrorCode = RecvFrom(m_pRecvBuffer, nLen, RemoteIp, RemotePort);
    MkCheckErrorLog(ErrorCode, "recv buffer failed\n");
    if (0 == nLen) {
        MkErrorLog("buffer is empty\n");
        return SocketRecvFailed;
    }
    Uint32 nUsed = 0;
    if (GetParent()) {
        GetParent()->OnSipBufferRecved(m_pRecvBuffer, nLen, RemoteIp, RemotePort, GetLocalHost(), GetLocalPort(), FALSE, nUsed);
    }
    return NoneError;
}

CMkSipUdpListener::~CMkSipUdpListener()
{
    MkFree(m_pRecvBuffer);
}
